#pragma once
#include "mq_channal.hpp"
namespace mq_zxws
{
    class Connection{
    public:
        using ptr = std::shared_ptr<Connection>;
        Connection(const muduo::net::TcpConnectionPtr& conn, 
                const ProtobufCodecPtr& codec,
                const ConsumerManager::ptr& cmp,
                const VirtualHost::ptr& host,
                const ThreadPool::ptr& pool)
                :_conn(conn), _codec(codec), _cmp(cmp), _host(host), _pool(pool)
                ,_channals(std::make_shared<ChannalManager>())
            {}
        void openChannal(const openChannalRequestPtr& req){
            bool ret = _channals->openChannal(req->cid(), _conn, _codec, _cmp, _host, _pool);
            return basicResponce(ret, req->rid(), req->cid());
        }
        void closeChannal(const closeChannalRequestPtr& req){
            _channals->closeChannal(req->cid());
            return basicResponce(false, req->rid(), req->cid());
        }
        Channal::ptr getChannal(const std::string & cid){
            return _channals->getChannal(cid);
        }
    private:
        void basicResponce(bool ok, const std::string& rid, const std::string& cid){
            basicCommonResponce resp;
            resp.set_rid(rid);
            resp.set_cid(cid);
            resp.set_ok(ok);
            _codec->send(_conn, resp);
        }
    private:
        muduo::net::TcpConnectionPtr _conn;
        ProtobufCodecPtr _codec;
        ConsumerManager::ptr _cmp;
        VirtualHost::ptr _host;
        ThreadPool::ptr _pool;
        ChannalManager::ptr _channals;
    };

    class ConnectionManager{
    public:
        using ptr = std::shared_ptr<ConnectionManager>;
        ConnectionManager(){}
        void newConnection(const muduo::net::TcpConnectionPtr& conn, 
                const ProtobufCodecPtr& codec,
                const ConsumerManager::ptr& cmp,
                const VirtualHost::ptr& host,
                const ThreadPool::ptr& pool)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end()){
                Connection::ptr cp = std::make_shared<Connection>(conn, codec, cmp, host, pool);
                DLOG("新增连接成功");
                _conns.insert(std::make_pair(conn, cp));
            }
        }
        void deleteConnection(const muduo::net::TcpConnectionPtr& conn){
            std::unique_lock<std::mutex> lock(_mutex);
            _conns.erase(conn);
        }
        Connection::ptr getConnection(const muduo::net::TcpConnectionPtr& conn){
            std::unique_lock<std::mutex> lock(_mutex);
            auto it = _conns.find(conn);
            if(it == _conns.end()){
                return Connection::ptr();
            }
            return it->second;
        }
    private:
        std::mutex _mutex;
        std::unordered_map<muduo::net::TcpConnectionPtr, Connection::ptr> _conns;
    };
}